home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / uupc 3.1 / (uupc π) / dcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-05  |  20.2 KB  |  941 lines  |  [TEXT/KAHL]

  1. /*            dcp.c
  2.  
  3.             Revised edition of dcp
  4.  
  5.             Stuart Lynne May/87
  6.  
  7.             Copyright (c) Richard H. Lamb 1985, 1986, 1987
  8.             Changes Copyright (c) Stuart Lynne 1987
  9.             
  10.             Portions Copyright © David Platt, 1992, 1991.  All Rights Reserved
  11.             Worldwide.
  12.  
  13. */
  14. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  15. /* This program implements a uucico type file transfer and remote
  16. execution type protocol.
  17. */
  18. #include "dcp.h"                /**/
  19. #include <Power.h>
  20. #include <GestaltEqu.h>            /* BH-C */
  21. #include <stdarg.h>
  22.  
  23. FILE    *logfile;                /* system log file */
  24. FILE    *syslog;                /* system log file */
  25. FILE    *fw;                     /* cfile pointer */
  26. char    state;                    /* system state*/
  27. char    cfile[80];              /* work file pointer */
  28. int        remote;                 /* -1 means we're remote ..7*/
  29. int        del_file_flag;            /* means delete file(s) at end of xfer */
  30. int        msgtime;                /* timout setting */
  31. char    fromfile[132];
  32. char    rmtfname[132];
  33. char    hostfile[132];            /* host version of fromfile */
  34. char    tofile[132];
  35. int        fp;                     /* current disk file ptr */
  36. int        size;                   /* nbytes in buff */
  37. int        pktsize;                /* packet size for this protocol*/
  38. int     xfer_problems;
  39. int      useHardwareFlowControl;
  40. FILE    *fsys;
  41. char    Rmtname[20];
  42. char    rmtname[20];
  43. char    gotname[20];
  44. char    callcause[64];
  45. char    * cctime;
  46. char    proto[5];
  47. /* char    loginseq[256]; */
  48. char     sysline[BUFSIZ*2];
  49. char    s_systems[64];
  50. char    s_logfile[64];
  51. char    s_syslog[64];
  52. char    s_schedule[64];
  53. char    s_statfile[64];
  54. char     *flds[60];
  55. int     kflds;
  56. int        failureCount;
  57. time_t    theTime;
  58. time_t    runStartSecs;
  59.  
  60. int        PacketTimeout = 5;
  61. int        MaxErr = 20;
  62. int        xfer_retries_left;
  63.  
  64.  
  65. struct HostStats remote_stats; /* host status, as defined by hostatus */
  66. status_record Last;
  67. ConnectionHandler *currentConnection;
  68.  
  69. unsigned int    checksum();
  70.  
  71.  
  72. /**/
  73. /* new usage
  74.  
  75.     dcp    [-xn] -r0        slave mode
  76.     dcp    [-xn] -shost     call host
  77.     dcp    [-xn] -sall        call all hosts
  78.     dcp    [-xn] -sany        call any hosts as required by C. files
  79.     dcp [-xn] -scron    call hosts at times specified in cron file
  80.     dcp [-xn] -sneed    call hosts per cron-file schedule or if work is pending
  81.     dcp [-xn] -sauto    call hosts per cron-file schedule or if work is pending,
  82.                         and accept incoming calls between times
  83.  
  84. */
  85.  
  86. complain(char *s)
  87. {
  88.     fprintf( stderr, "Please set your %s environment variable.", s );
  89. }
  90.  
  91. int cant(char *file)
  92. {
  93.     fprintf( stderr, "Can't open: \"%s\"\n", file );
  94.     return (FAILED);
  95. }
  96.  
  97. int dcpmain(int argc, char **argv)
  98. {
  99.     char    line[132];
  100.     int    Line_Open = FALSE;
  101.     int Status = OK;            /* OK */
  102.     int active, first;
  103.     int realremote;
  104.     int waitforever;
  105.     int callup_for_inbound;
  106.     int quit, shutdown;
  107.     int could_slave, did_slave;
  108.     int once;
  109.     int runTimeout;
  110.     long    startSecs;
  111.     long    wakeupSecs;
  112.     long    oldWakeupSecs;
  113.     long    powerManagerFlags;
  114.     Byte    wakeupFlag;
  115.     long    Start_Ticks;
  116.     long    Session_Start_Ticks;
  117.     long    minutes_to_sleep;
  118.     OSErr    wakeupError;
  119.     
  120.     if ( name == NULL || *name == '\0' ) {
  121.         complain( NAME );
  122.         return (FAILED);
  123.     }
  124.     if ( nodename == NULL || *nodename == '\0' ) {
  125.         complain( NODENAME );
  126.         return (FAILED);
  127.     }
  128.     time(&theTime);
  129.     if (Gestalt(gestaltPowerMgrAttr,&powerManagerFlags) != noErr) {
  130.         powerManagerFlags = 0;
  131.     }
  132.  
  133.     mkfilename( line, spooldir, LOGFILE );
  134.     if (strchr(spooldir, SEPCHAR) == NULL && strchr(spooldir, DIRCHAR) == NULL)
  135.         /* make it an absolute pathname */
  136.         mkfilename(s_logfile, curdir, line);
  137.     else
  138.         strcpy(s_logfile, line);
  139.         
  140.     mkfilename( line,  spooldir, SYSLOG  );
  141.     if (strchr(spooldir, SEPCHAR) == NULL && strchr(spooldir, DIRCHAR) == NULL)
  142.         /* make it an absolute pathname */
  143.         mkfilename(s_syslog, curdir, line);
  144.     else
  145.         strcpy(s_syslog, line);
  146.         
  147.     mkfilename( line, confdir,  SYSTEMS );
  148.     if (strchr(confdir, SEPCHAR) == NULL && strchr(confdir, DIRCHAR) == NULL)
  149.         /* make it an absolute pathname */
  150.         mkfilename(s_systems, curdir, line);
  151.     else
  152.         strcpy(s_systems, line);
  153.         
  154.     mkfilename( line, confdir, SCHEDULE );
  155.     if (strchr(confdir, SEPCHAR) == NULL && strchr(confdir, DIRCHAR) == NULL)
  156.         /* make it an absolute pathname */
  157.         mkfilename(s_schedule, curdir, line);
  158.     else
  159.         strcpy(s_schedule, line);
  160.  
  161.     mkfilename( line, spooldir, STATFILE );
  162.     if (strchr(spooldir, SEPCHAR) == NULL && strchr(spooldir, DIRCHAR) == NULL)
  163.         /* make it an absolute pathname */
  164.         mkfilename(s_statfile, curdir, line);
  165.     else
  166.         strcpy(s_statfile, line);
  167.         
  168.     Status = OK;
  169.     remote = MASTER;
  170.     debuglevel = 0;
  171.     active = FALSE;
  172.     first = TRUE;
  173.     quit = FALSE;
  174.     shutdown = FALSE;
  175.     once = FALSE;
  176.     runTimeout = -1;
  177.     Session_Start_Ticks = TickCount();
  178.  
  179.     strcpy( Rmtname, "any" );        /* default */
  180.     fw = (FILE *) NULL;
  181.     
  182.     while ( argc ) {
  183.         if ( **argv == '-') {
  184.             switch(argv[0][1]) {
  185.             case 'x':
  186.                 debuglevel = atoi( &argv[0][2] );
  187.                 printmsg(1, "Debug level set to %d", debuglevel);
  188.                 break;
  189.             case 's':
  190.                 strcpy (Rmtname, &argv[0][2]);
  191.                 break;
  192.             case 'r':
  193.                 remote = atoi( &argv[0][2] );
  194.                 break;
  195.             case 'q':
  196.                 quit = TRUE;
  197.                 printmsg(1, "Quit-after-run flag set");
  198.                 break;
  199.             case 'S':
  200.                 shutdown = TRUE;
  201.                 printmsg(1, "Shutdown-after-run flag set");
  202.                 break;
  203.             case 'o':
  204.                 once = TRUE;
  205.                 printmsg(1, "One-run flag set");
  206.                 break;
  207.             case 't':
  208.                 sscanf(argv[0]+2, "%d", &runTimeout);
  209.                 printmsg(1, "Timeout set to %d minutes", runTimeout);
  210.                 break;
  211.  
  212.             default:
  213.                 break;
  214.             }
  215.         }
  216.         argv++;
  217.         argc--;
  218.     }
  219.  
  220.     realremote = remote;
  221.  
  222. main_loop:
  223.  
  224.     if (dcxqt())
  225.         printmsg( 0, "ERROR in DCXQT" );
  226.  
  227.     if (logfile != (FILE *) NULL)  
  228.         printmsg( 0, "logfile already open" );
  229.     if (syslog != (FILE *) NULL)  
  230.         printmsg( 0, "syslog already open" );
  231.  
  232.     /* reopen log each time */
  233.     if ( (logfile = FOPEN( s_logfile, "a", 't' )) == NULL )
  234.        return(cant(s_logfile));
  235.     if ( (syslog  = FOPEN( s_syslog,  "a", 't' )) == NULL )
  236.        return(cant(s_syslog));
  237.     
  238. start_next_run:
  239.  
  240. #ifdef Upgrade
  241.     systimeout = 0;
  242.     active = FALSE;
  243.     did_slave = FALSE;
  244.     could_slave = FALSE;
  245.     gotname[0] = 0;
  246.     remote = realremote;
  247.     time(&runStartSecs);
  248.     Last.name[0] = '\0';
  249.     rmtname[0] = '\0';
  250. #endif Upgrade
  251.     fp = -1;
  252.     if (fw != (FILE *)NULL) {
  253.         fclose(fw);
  254.         fw = (FILE *)NULL;
  255.     }
  256.     
  257. #ifdef MULTIFINDER
  258.     Start_Ticks = TickCount();
  259. #endif
  260.     
  261.     if ( remote == MASTER ) {
  262.          printmsg( 1, "Calling %s, debuglevel=%d", Rmtname, debuglevel );
  263.         state = 'I';
  264.         xfer_problems = 0;
  265.  
  266.         if (fsys != (FILE *) NULL)  
  267.             fprintf( stderr, "fsys already open" );
  268.         if (( fsys = FOPEN( s_systems, "r", 't' )) == (FILE *)NULL ) {
  269.             printmsg(0, "Error %d, can't open %s file!", errno, s_systems);
  270.             Status = FAILED;
  271.             goto abort;
  272.         }
  273.  
  274.         while (TRUE) {
  275. #ifdef MULTIFINDER
  276.             Check_Events(MF_DELAY);
  277. #endif
  278.             printmsg( 4, "Mstate = %c", state );
  279.             switch (state) {
  280.             case 'I':
  281.                 if (Check_Events(MF_DELAY)) goto abort;
  282.                 systimeout = 0;
  283.                 state = getsystem(Rmtname);
  284.                 if (state != 'A' && strcmp(Rmtname, gotname) == SAME) {
  285.                     state = 'I'; /* dplatt, don't repeat successful call on different line */
  286.                 }
  287.                 break;
  288.             case 'T':
  289.                 state = 'I';
  290.                 break;
  291.             case 'S':
  292.                 active = TRUE;
  293.                 state = callup();
  294.                 break;
  295.             case 'P':
  296.                 (*currentConnection->AllowInterrupts)(FALSE);
  297.                 state = startup();
  298.                 break;
  299.             case 'D':
  300.                 state = master();
  301.                 break;
  302.             case 'Y':
  303.                 state = sysend();
  304.                 if (xfer_problems > 0) {
  305.                     printmsg( 0, "Bad Things happened during that call");
  306.                     failureCount ++;
  307.                     Status = FAILED;
  308.                 } else {
  309.                     Status = OK;
  310.                 }
  311.                 Update_Status(Status);
  312.                 if ((strcmp(Rmtname, "any")  != SAME) &&
  313.                     (strcmp(Rmtname, "all")  != SAME) &&
  314.                     (strcmp(Rmtname, "cron") != SAME) &&
  315.                     (strcmp(Rmtname, "need") != SAME) &&
  316.                     (strcmp(Rmtname, "auto") != SAME)) {
  317.                     state = 'A';
  318.                 } else {
  319.                     strcpy(gotname, rmtname); /* remember who we got */
  320.                 }
  321.                 break;
  322.             case 'G':
  323.                 if ((strcmp(Rmtname, "any")  == SAME) ||
  324.                     (strcmp(Rmtname, "all")  == SAME) ||
  325.                     (strcmp(Rmtname, "cron") == SAME) ||
  326.                     (strcmp(Rmtname, "need") == SAME) ||
  327.                     (strcmp(Rmtname, "auto") == SAME))
  328.                     state = 'I';
  329.                 else
  330.                     state = 'Y';
  331.                 break;
  332.             case 'X':
  333.                 closeline();
  334.                 Line_Open = FALSE;
  335.                 Status = FAILED;    /* I think this is always failure */
  336.                 printmsg( 0, "Call failed");
  337.                 failureCount ++;
  338.                 Update_Status(FAILED);
  339.                 state = 'I';
  340.                 break;
  341.             }
  342.             if (state == 'A') {
  343.                 if (Line_Open) {
  344.                     printmsg(0, "Disconnecting");
  345.                     closeline();
  346.                     Line_Open = FALSE;
  347.                 }
  348.                 rmtname[0] = 0;        /* zap name so it won't be in log anymore */
  349.                 if (fw != (FILE *)NULL) {
  350.                     fclose(fw);
  351.                     fw = (FILE *)NULL;
  352.                 }
  353.                 if (fp != -1) {
  354.                     close(fp);
  355.                     fp = -1;
  356.                 }
  357.                 break;
  358.             }
  359.         }
  360.         if (logfile != (FILE *)NULL) {
  361.             fflush(logfile);
  362.         }
  363.     }
  364.  
  365.     if (fsys != (FILE *)NULL) {
  366.         fclose( fsys );
  367.         fsys = (FILE *)NULL;
  368.     }
  369.  
  370.     if (Main_State != Call_Systems) goto abort;
  371.     
  372.     if (active) {
  373.         if (dcxqt())
  374.             printmsg( 0, "ERROR in DCXQT" );
  375.     }
  376.     
  377.     if (remote == SLAVE || strcmp(Rmtname, "auto") == SAME) {
  378.     
  379.         /**** SLAVE MODE (wait for calls) ****/
  380.         
  381.         waitforever = TRUE;
  382.         if (strcmp(Rmtname, "auto") == SAME || once) {
  383.             waitforever = FALSE;
  384.         }
  385.         
  386.         if (fsys != (FILE *) NULL)  
  387.             fprintf( stderr, "fsys already open" );
  388.         if (( fsys = FOPEN( s_systems, "r", 't' )) == (FILE *)NULL ) {
  389.             printmsg(0, "Error %d, can't open %s file!", errno, s_systems);
  390.             Status = FAILED;
  391.             goto abort;
  392.         }
  393.  
  394.         remote = SLAVE;
  395.         callup_for_inbound = FALSE;
  396.         do {
  397.             state = getsystem("INCOMING");
  398.             if (state == 'S' || state == 'T') could_slave = TRUE;
  399.         } while (state != 'S' && state != 'A');
  400.         rmtname[0] = '\0';
  401.  
  402.         if (state != 'S') {
  403.             goto no_slave;
  404.         }
  405.         did_slave = TRUE;
  406.             
  407.         if (active || first) {
  408.             printmsg(0, "Awaiting incoming call");
  409.         }
  410.         while (TRUE) {
  411. #ifdef MULTIFINDER
  412.             if (Check_Events(MF_DELAY)) goto killincoming;
  413. #endif
  414.             printmsg( 4, "Sstate = %c", state );
  415.             switch (state) {
  416.             case 'S':
  417.                 state = callup();
  418.                 callup_for_inbound = TRUE;
  419.                 break;
  420.             case 'P':
  421.                 Line_Open = TRUE;
  422.                 state = login(waitforever, callup_for_inbound);
  423.                 break;
  424.             case 'I':
  425.                 active = TRUE;
  426.                 (*currentConnection->AllowInterrupts)(FALSE);
  427.                 PlayNamed("\pIncoming");
  428.                 state = startup();
  429.                 break;
  430.             case 'R':
  431.                 state = slave();
  432.                 break;
  433.             case 'Y':
  434.                 state = sysend();
  435.                 break;
  436.             case 'X':
  437.                 state = 'A';
  438.                 break;
  439.             }
  440.             if (state == 'A') {
  441.                 break;
  442.             }
  443.         }
  444. killincoming:
  445.         closeline();
  446.         Line_Open = FALSE;
  447. no_slave: ;
  448.     }
  449.     
  450.     if (fsys != (FILE *)NULL) {
  451.         fclose( fsys );
  452.         fsys = (FILE *)NULL;
  453.     }
  454.  
  455.     if (logfile != (FILE *)NULL) {
  456.         fflush(logfile);
  457.     }
  458.  
  459.     if (Main_State != Call_Systems) goto abort;
  460.     
  461.     if (dcxqt())
  462.         printmsg( 0, "ERROR in DCXQT" );
  463.     
  464.     if (active) printmsg( 0, "Session completed");
  465.     
  466.     if (once || runTimeout < 0 || (TickCount() - Session_Start_Ticks) / 3600 >= runTimeout) {    
  467.         if (quit) {
  468.             printmsg(0, "Quitting");
  469.             Main_State = Quit_Program;
  470.             goto abort;
  471.         }
  472.         if (shutdown) {
  473.             printmsg(0, "Shutting down");
  474.             Main_State = Shutdown_Program;
  475.             goto abort;
  476.         }
  477.     }
  478.     
  479.     if (once) {
  480.         printmsg(1, "Exiting due to one-run flag");
  481.         goto abort;
  482.     }
  483.     
  484.     if (runTimeout >= 0 && (TickCount() - Session_Start_Ticks) / 3600 >= runTimeout) {
  485.         printmsg(1, "Exiting due to timeout");
  486.         goto abort;
  487.     }
  488.     
  489.     if (strcmp(Rmtname, "auto") == SAME || realremote == SLAVE) {
  490.         /* in these modes we never exit;  most of the time is spent in slave mode,
  491.            waiting for an inbound call to occur. */
  492.         if (!did_slave) {
  493.             if (active || first) {
  494.                 if (!could_slave) {
  495.                     printmsg(0, "No INCOMING entry in Systems file, cannot accept calls");
  496.                     if (realremote == SLAVE) goto abort;
  497.                 } else {
  498.                     printmsg(0, "Ineligible for incoming calls at this time; sleeping");
  499.                 }
  500.             }
  501.             goto sleep_a_while;
  502.         }
  503.         first = FALSE;
  504.         goto start_next_run;
  505.     }
  506.         
  507.     if (strcmp(Rmtname,"cron") == SAME || strcmp(Rmtname,"need") == SAME) {
  508.         /* in cron and need mode, we never exit, we just keep waiting for a time to call
  509.            some system */
  510.  
  511.         if (active || first) printmsg(0, "Sleeping to await next scheduled call");
  512.         
  513. sleep_a_while:
  514.         
  515.         first = FALSE;
  516.  
  517.         /* close logfile while we're not using it */
  518.         if (syslog != (FILE *)NULL) {
  519.             fclose(syslog);
  520.             syslog = (FILE *)NULL;
  521.         }
  522.         if (logfile != (FILE *)NULL) {
  523.             fclose(logfile);
  524.             logfile = (FILE *)NULL;
  525.         }
  526.         
  527. #ifdef MULTIFINDER
  528.         sscanf(sleeptime, "%ld", &minutes_to_sleep);
  529.         if (minutes_to_sleep < 1) minutes_to_sleep = 1;
  530.         /* wait for a few minutes and then see if there is anything to do yet */
  531.         Start_Ticks = TickCount();
  532.         if (powerManagerFlags & (1L << gestaltPMgrExists)) {
  533.             printmsg(1, "Reading current time");
  534.             ReadDateTime(&startSecs);
  535.             wakeupSecs = startSecs + minutes_to_sleep * 60 + 2;
  536.             printmsg(1, "Reading current wakeup time");
  537.             if (noErr == (wakeupError = GetWUTime(&oldWakeupSecs, &wakeupFlag))) {
  538.                 if ((wakeupFlag & 1) == 0 ||
  539.                  oldWakeupSecs <= startSecs ||
  540.                  oldWakeupSecs > wakeupSecs) {
  541.                      printmsg(1, "Setting new wakeup time");
  542.                     if (noErr != (wakeupError = SetWUTime(wakeupSecs))) {
  543.                         printmsg(0, "Error %d trying to set wakeup timer", wakeupError);
  544.                     }
  545.                 }
  546.             } else {
  547.                 printmsg(0, "Error %d trying to read wakeup timer", wakeupError);
  548.             }
  549.         }
  550.         printmsg(0, "Sleeping");
  551.         while (TickCount()-Start_Ticks < minutes_to_sleep * 3600) {
  552.             if (Check_Events(60)) goto abort;    /* allow a 1 second wait */
  553.         }
  554. #endif
  555.         goto main_loop;
  556.     }
  557.  
  558.     /* scan and process any recieved files */
  559. abort:
  560.     if (syslog != (FILE *)NULL) {
  561.         fclose(syslog);
  562.         syslog = (FILE *)NULL;
  563.     }
  564.     if (logfile != (FILE *)NULL) {
  565.         fclose(logfile);
  566.         logfile = (FILE *)NULL;
  567.     }
  568.     
  569.     if (Line_Open) closeline();
  570.     return Status;
  571. }
  572.  
  573.  
  574. /**/
  575. /*
  576. **
  577. **
  578. **master
  579. **
  580. **
  581. */
  582. master(void)
  583. {
  584.     state = 'I';
  585.     while (TRUE) {
  586.         printmsg( 4, "Top level state (master mode) %c", state );
  587.         switch (state) {
  588.         case 'I':
  589.             state = sinit();
  590.             break;
  591.         case 'B':
  592.             state = scandir();
  593.             break;
  594.         case 'S':
  595.             state = send();
  596.             break;
  597.         case 'Q':
  598.             state = sbreak();
  599.             break;
  600.         case 'G':
  601.             state = receive();
  602.             break;
  603.         case 'C':
  604.             state = schkdir();
  605.             break;
  606.         case 'Y':
  607.             state = endp(TRUE);
  608.             break;
  609.         case 'H':
  610.             state = endp(FALSE);
  611.             break;
  612.         case 'P':
  613.             return('Y');
  614.         case 'A':
  615.             return('A');
  616.         case 'X':
  617.             return('X');
  618.         default:
  619.             return('A');
  620.         }
  621.     }
  622. }
  623.  
  624.  
  625. /**/
  626. /*
  627. **
  628. **
  629. **slave
  630. **
  631. **
  632. */
  633. slave(void)
  634. {
  635.     state = 'I';
  636.     while (TRUE) {
  637.         printmsg( 4, "Top level state (slave mode) %c", state );
  638.         switch (state) {
  639.         case 'I':
  640.             state = rinit();
  641.             break;
  642.         case 'F':
  643.             state = receive();
  644.             break;
  645.         case 'C':
  646.             state = schkdir();
  647.             break;
  648.         case 'T':
  649.             state = 'B';
  650.             break;
  651.         case 'B':
  652.             state = scandir();
  653.             break;
  654.         case 'S':
  655.             state = send();
  656.             break;
  657.         case 'Q':
  658.             state = sbreak();
  659.             break;
  660.         case 'G':
  661.             return('Y');
  662.         case 'Y':
  663.             state = endp(TRUE);
  664.             break;
  665.         case 'H':
  666.             state = endp(FALSE);
  667.             break;
  668.         case 'P':
  669.             return('Y');
  670.         case 'A':
  671.             return('A');
  672.         default:
  673.             return('A');
  674.         }
  675.     }
  676. }
  677.  
  678.  
  679. /**/
  680. /*
  681.  *  r e c e i v e
  682.  *
  683.  *  This is the state table switcher for receiving files.
  684.  */
  685.  
  686. receive(void)
  687. {
  688.  
  689.     state = 'F';/* Receive-Init is the start state */
  690.  
  691.     while (TRUE) {
  692.         printmsg( 4, " receive state: %c", state );
  693.         switch (state)/* Do until done */ {
  694.         case 'F':
  695.             xfer_retries_left = MAX_XFER_RETRIES;
  696.             state = rfile();
  697.             break; /* Receive-File */
  698.         case 'D':
  699.             state = rdata();
  700.             break; /* Receive-Data */
  701.         case 'R':
  702.             if (--xfer_retries_left < 0) {
  703.                 printmsg(0, "Retry limit reached, bailing out");
  704.                 if (fp && fp != -1) {
  705.                     close(fp);
  706.                     fp = -1;
  707.                 }
  708.                 return ('Y');
  709.             }
  710.             printmsg(0, "retrying transfer");
  711.             makenull(fp);
  712.             (*filepkt)(); /* re-init for file transfer */
  713.             state = 'D'; /* received-data-corrupt, so try again */
  714.             xfer_problems ++;
  715.             break;
  716.         case 'C':
  717.             return('C');/* Complete state */
  718.         case 'S':               /* Send-data */
  719.             state = sdata();
  720.             break;
  721.         case 'Z':               /* Send-End-of-File */
  722.             state = seof();
  723.             break;
  724.         case 'A':
  725.             return('Y');/* "Abort" state */
  726.         case 'H':
  727.             return ('H'); /* Semi-polite hangup */
  728.         default:
  729.             return('Y');
  730.         }
  731.     }
  732. }
  733.  
  734.  
  735. /**/
  736. /*
  737.  *  s e n d
  738.  *
  739.  *  Sendsw is the state table switcher for sending files.  It loops until
  740.  *  either it finishes, or an error is encountered.  The routines called
  741.  *  by sendsw are responsible for changing the state.
  742.  *
  743.  */
  744. send(void)
  745. {
  746.     fp = -1;                /* reset file getter/opener */
  747.     state = 'F';/* Send initiate is the start state */
  748.  
  749.     while (TRUE)/* Do this as long as necessary */ {
  750.         printmsg( 4, "send state: %c", state );
  751.         switch (state) {
  752.         case 'F':
  753.             xfer_retries_left = MAX_XFER_RETRIES;
  754.             state = sfile();
  755.             break; /* Send-File */
  756.         case 'D':
  757.             state = sdata();
  758.             break; /* Send-Data */
  759.         case 'Z':
  760.             state = seof();
  761.             break; /* Send-End-of-File */
  762.         case 'R':                       /* Receive-data */
  763.             state = rdata();
  764.             if (state == 'D')          /* re-interpret the state! */
  765.                  state = 'R';
  766.             else if (state == 'R')
  767.                  state = 'T';            /* uglier yet... dplatt */
  768.             break;
  769.         case 'T':
  770.             if (--xfer_retries_left < 0) {
  771.                 printmsg(0, "Retry limit reached, bailing out");
  772.                 if (fp && fp != -1) {
  773.                     close(fp);
  774.                     fp = -1;
  775.                 }
  776.                 return ('Y');
  777.             }
  778.             printmsg(0, "retrying transfer");
  779.             makenull(fp);
  780.             (*filepkt)(); /* re-init for file transfer */
  781.             state = 'R'; /* received-data-corrupt, so try again */
  782.             xfer_problems ++;
  783.             break;
  784.         case 'B':
  785.             return ('B'); /* Complete */
  786.         case 'A':
  787.             return ('Y'); /* "Abort" */
  788.         case 'H':
  789.             return ('H'); /* Semi-polite hangup */
  790.         default:
  791.             return ('Y'); /* Unknown, fail */
  792.         }
  793.     }
  794. }
  795.  
  796.  
  797. /**/
  798. /* A command formatter for DCP. RH Lamb */
  799. /* sets up stdin and stdout on various machines */
  800. /* There is NO command checking so watch what you send and who you */
  801. /* let accsess your machine. "C rm /usr/*.*" could be executed. */
  802. dcxqt(void)
  803. {
  804.     int    i;
  805.     char    command[CMDBUFSIZE], input[60], output[60], reqd[60], line[CMDBUFSIZE];
  806.     char    *cp;
  807.     int status = 0;
  808.     
  809.     while (dscandir()) {
  810.         strcpy( line, cfile );
  811.         fw = FOPEN( line, "r", 't' );/* imported X file */
  812.         strcpy(cfile, line);
  813.         printmsg( 2, "dcxqt:%s %ld", cfile, fw );
  814.         input[0]   = '\0';
  815.         output[0]  = '\0';
  816.         command[0] = '\0';
  817.         reqd[0] = '\0';
  818.         gotitfrom[0] = '\0';
  819.         gotfromuser[0] = '\0';
  820.         while ( fgets( line, BUFSIZ, fw ) != (char *)NULL ) {
  821.  
  822. #ifdef MULTIFINDER
  823.             status = Check_Events(MF_DELAY);
  824. #endif
  825.             cp = index( line, '\n' );
  826.             if ( cp != (char *)NULL )
  827.                 *cp = '\0';
  828.  
  829.             printmsg( 8, "dcxqt: %s", line );
  830.             switch (line[0]) {
  831.             case 'U':
  832.                 sscanf(line, "U%*[ ]%s%*[ ]%s", gotfromuser, gotitfrom);
  833.                 printmsg (5, "<%s> user=%s site=%s", line, gotfromuser, gotitfrom);
  834.                 break;
  835.             case 'I':
  836.                 strcpy( input,   line+2 );
  837.                 break;
  838.             case 'O':
  839.                 strcpy( output,  line+2 );
  840.                 break;
  841.             case 'C':
  842.                 strcpy( command, line+2 );
  843.                 break;
  844.             case 'F':
  845.                 strcpy( reqd, line+2 );
  846.                 break;
  847.             case 'R':
  848.             case '#':
  849.             case 'Z':
  850.             case 'N':
  851.                 break;    /* not implemented */
  852.             default :
  853.                 break;
  854.             }
  855.         }
  856.         if (fw != (FILE *)NULL) {
  857.             fclose(fw);
  858.             fw = (FILE *)NULL;
  859.         }
  860.         
  861.         if (strlen(gotitfrom) > 0 && strlen(gotfromuser) > 0) {
  862.             printmsg(0, "%s!%s: %s", gotitfrom, gotfromuser, command );
  863.         } else {
  864.             printmsg(0, "XQT %s", command );
  865.         }
  866.  
  867.         if (shell(command, input, output)) {
  868.             UNLINK(cfile);
  869.             if (strlen(input) > 0) {
  870.                  importpath( hostfile, input );
  871.                  UNLINK(hostfile);
  872.              }
  873.             if (strlen(output) > 0) {
  874.                 importpath( hostfile, output );
  875.                  UNLINK(hostfile);
  876.              }
  877.          } else {
  878.              return(1); /* Trouble;  bail out */
  879.          }
  880.          if (status) return(0);    /* cancel operations */
  881.     }
  882.     return(0);
  883. }
  884.  
  885. /**/
  886. /*
  887.  *  p r i n t m s g
  888.  *
  889.  *  Print error message on standard output if not remote.
  890.  */
  891. /*VARARGS1*/
  892. printmsg(int level, char *fmt, ...)
  893. {
  894.     char    msg[BUFSIZ*2];
  895. #ifdef    THINK_C
  896.     static    char    loghdr[50]={0};
  897.     struct tm        *t;
  898.     va_list ap;
  899. #endif    THINK_C
  900.     if ( debuglevel >= level ) {
  901. #ifdef  THINK_C
  902.         time(&theTime);
  903.         t = localtime(&theTime);
  904. #ifdef MULTIFINDER
  905.         printf( "%02d:%02d:%02d ", t->tm_hour, t->tm_min, t->tm_sec );
  906. #else
  907.         if ( remote == MASTER  || strcmp(Rmtname, "auto") == SAME) {
  908.             printf( "%02d:%02d:%02d ", t->tm_hour, t->tm_min, t->tm_sec );
  909.         }
  910. #endif
  911. #endif
  912.         va_start(ap, fmt);
  913.         vsprintf( msg, fmt, ap );
  914.         va_end(ap);
  915. #ifdef MULTIFINDER
  916.         fputs(msg, stdout);
  917.         fputc('\n', stdout);
  918. #else
  919.         if ( remote == MASTER || strcmp(Rmtname, "auto") == SAME) {
  920.             fputs(msg, stdout);
  921.             fputc('\n', stdout);
  922.         }
  923. #endif
  924. #ifdef    THINK_C
  925.             if (level <= 5 && logfile) {
  926.                 fprintf(logfile, "%-8s %02d/%02d-%02d:%02d (%s)\n",
  927.                             /* (remote == MASTER)?nodename : rmtname, */
  928.                             rmtname,
  929.                             t->tm_mday, t->tm_mon+1,
  930.                             t->tm_hour, t->tm_min,
  931.                             msg);
  932.             }
  933. #else    THINK_C
  934.         if (logfile) {
  935.             fputs( msg, logfile );
  936.             fputc( '\n', logfile);
  937.         }
  938. #endif    THINK_C
  939.     }
  940. }
  941.